package io.renren.socket;

import io.renren.service.DemoService;
import io.renren.util.SpringUtil;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.nio.charset.Charset;
import java.util.*;

/** * nio socket服务端 */
public class SocketServer {


    //解码buffer
    private Charset cs = Charset.forName("GBK");
    // 接受数据缓冲区
    private static ByteBuffer sBuffer = ByteBuffer.allocate(1024);
    //发送数据缓冲区
    private static ByteBuffer rBuffer = ByteBuffer.allocate(1024);
    //选择器（叫监听器更准确些吧应该）
    public static Selector selector;
    private DemoService demoService = SpringUtil.getBean(DemoService.class);

    /**
     * 启动socket服务，开启监听     * @param port     * @throws IOException
     */
    public void startSocketServer(int port) {
        try {
            //打开通信信道
            ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
            //设置为非阻塞
            serverSocketChannel.configureBlocking(false);
            //获取套接字
            ServerSocket serverSocket = serverSocketChannel.socket();
            //绑定端口号
            serverSocket.bind(new InetSocketAddress(port));
            //打开监听器
            selector = Selector.open();
            //将通信信道注册到监听器
            serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
            //监听器会一直监听，如果客户端有请求就会进入相应的事件处理
            try {
                System.out.println("我又重启了");
                while (true) {
                    selector.select();
                    //select方法会一直阻塞直到有相关事件发生或超时
                    EEs.selectionKeys = selector.selectedKeys();//监听到的事件
                    for (SelectionKey key : EEs.selectionKeys) {
                        handle(key, EEs.selectionKeys);
                    }
                    EEs.selectionKeys.clear();
                    //清除处理过的事件
                }

            } catch (IOException e) {
                e.printStackTrace();
                //          startSelector();
            }
        } catch (Exception e) {
            e.printStackTrace();
            // startSelector();

        }
    }

    private void startSelector() {

    }

    /**
     * 处理不同的事件     * @param selectionKey     * @throws IOException
     */
    private void handle(SelectionKey selectionKey, Set<SelectionKey> selectionKeys) throws IOException {
        ServerSocketChannel serverSocketChannel = null;
        SocketChannel socketChannel = null;
        String requestMsg = "";
        int count = 0;
        try {
            if (selectionKey.isAcceptable()) {
                //每有客户端连接，即注册通信信道为可读
                serverSocketChannel = (ServerSocketChannel) selectionKey.channel();

                socketChannel = serverSocketChannel.accept();
                socketChannel.configureBlocking(false);
                socketChannel.register(selector, SelectionKey.OP_READ);
            } else if (selectionKey.isReadable()) {
                socketChannel = (SocketChannel) selectionKey.channel();
                rBuffer.clear();
                count = socketChannel.read(rBuffer);
                List chars = new ArrayList();
                String r = "";
                //读取数据
                if (count > 0) {
                    rBuffer.flip();
                    // b=rBuffer.array();
                    requestMsg = String.valueOf(cs.decode(rBuffer).array());
                    r = str2HexStr(rBuffer.array(), count);
                    // System.out.println(r);
                }
                //数据解析todo
                if ("".equals(r)) {
                    //    demoService.saveService("已断开:"+selectionKey.channel().toString());
                    socketChannel.close();
                } else if (r.substring(0, 6).equals("5A5A5A")) {
                    CommContent c = null;
                    c = EEs.setCommContent(r);
                    EEs.setEquipmentEntitys(c, selectionKey);
                    System.out.println(c.toString());

                    setMachine(c);


                } else {
                    System.out.println("数据有误");
                }

                //   demoService.saveService(r + selectionKey.channel().toString());


//                //数据解析todo
////if(r.length())
//                System.out.println(r.length());
////                for(int i=0;i<r.length();i++){
////                    System.out.println(r.substring(i,i+1)+"   "+i);
////                }
//                CommContent c =null;
//                if(r.length()==40){
//                    c= EEs.setCommContent(r);
//                }
//                if(r.equals("")){
//                    demoService.saveService("已断开:"+selectionKey.channel().toString());
//                    socketChannel.close();
//                }else if(c!=null) {
//                   // CommContent c = EEs.setCommContent(r);
//                    EEs.setEquipmentEntitys(c, selectionKey);
//                    Machine m = new Machine();
//                    //    if(r.length()<)
//                    if (c.getFunction().equals("01")) {
//                        String data = c.getData();  //获取数据
//                        String str = data.substring(0, 2);  //获取数据的第一个字节
//                        //System.out.println(data);
//                        if (str.equals("00")) {
//                            //第一个字节是00 代表温度是正的
//                            int wd10 = Integer.parseInt(c.getData(), 16);
//                            String w = wd10 + "";  //转成字符串
//                            String wLast = w.substring(w.length() - 1, w.length());  //获取字符串的最后一位数据
//                            String wdf = "" + (wd10 / 10) + "." + wLast;  //拼接
//                            EEs.machine.setTemperature("+" + wdf);
//                        } else if (str.equals("01")) {
//                            //第一个字节是01 代表温度是负的
//                            data = data.replace(data.substring(0, 2), "00");
//                            int wd10 = Integer.parseInt(data, 16);// 283
//                            String w = wd10 + "";  //转成字符串
//                            String wLast = w.substring(w.length() - 1, w.length());  //获取字符串的最后一位数据
//                            String wdf = "" + (wd10 / 10) + "." + wLast;  //拼接
//                            EEs.machine.setTemperature("-" + wdf);
//                        } else {
//                            EEs.machine.setTemperature("数据传输有误");
//                        }
//
//                    } else if (c.getFunction().equals("02")) {
//                        //湿度
//                        EEs.machine.setHumidity(Integer.parseInt(c.getData(), 16) + "");
//                    } else if (c.getFunction().equals("03")) {
//                        //风向
//                        EEs.machine.setWindDirection(Integer.parseInt(c.getData(), 16) + "");
//                    } else if (c.getFunction().equals("04")) {
//                        //风速
//                        //m.setWindSpeed((Integer.parseInt(c.getData(),16) / 10 )+"");
//                        int fs10 = Integer.parseInt(c.getData(), 16);
//                        String w = fs10 + "";  //转成字符串
//                        String wLast = w.substring(w.length() - 1, w.length());  //获取字符串的最后一位数据
//                        String fsf = "" + (fs10 / 10) + "." + wLast;  //拼接
//                        EEs.machine.setWindSpeed(fsf);
//                    } else if (c.getFunction().equals("05")) {
//                        EEs.machine.setBeiruqin(true);
////               //电子围栏    开关量
//                        String data = c.getData();
//                        String str = data.substring(data.length() - 1, data.length());
//                        if (str.equals("1")) {
//                            EEs.machine.setBeiruqin(true);
//                        } else {
//                            EEs.machine.setBeiruqin(false);
//                        }
//                    } else if (c.getFunction().equals("06")) {
//                        //红外感应    开关量
//                        //m.setElectronicFence((Integer.parseInt(c.getData(),16))+"");
//                        //EEs.machine.setElectronicFence();
//                        String data = c.getData();
//                        String str = data.substring(data.length() - 1, data.length());
//                        if (str.equals("1")) {
//                            //检测到人体的存在
//                            EEs.machine.setInfraredInduction("有");
//                        } else {
//                            EEs.machine.setInfraredInduction("无");
//                        }
//                    } else if (c.getFunction().equals("07")) {
//                        //光照度传感器
//                        EEs.machine.setLightIntensity(Integer.parseInt(c.getData(), 16) + "");
//                    } else if (c.getFunction().equals("08")) {
//                        //烟雾传感器   开关量
//                        m.setSmokeSensor((Integer.parseInt(c.getData(), 16)) + "");
//                    }else if(c.getFunction().equals("09")){
//                        //触摸开关     开关量   前台显示即可
//                     //m.setTouchSwitch((Integer.parseInt(c.getData(),16))+"");
//                        if(c.getData().equals("000000000001")){
//                            EEs.machine.setTouchSwitch("开");
//                        }else {
//                            EEs.machine.setTouchSwitch("关");
//                        }
//
//           } else if (c.getFunction().equals("0b")) {
//                        // EEs.machine.setAlarmLamp(null);
//                        //光报警  0关  1开*****
//                        String data = c.getData();
//                        String str = data.substring(data.length() - 1, data.length());
//                        if (str.equals("1")) {
//                            //命令光报警打开
//                            EEs.machine.setAlarmLamp("01");
//                        } else {
//                            EEs.machine.setAlarmLamp("00");
//                        }
//                    } else if (c.getFunction().equals("12")) {
//                        //声报警  0关  1开******
//                        //m.setBuzzer((Integer.parseInt(c.getData(),16))+"");
//                        //  m.setBuzzer("00");
//                    } else if (c.getFunction().equals("13")) {
//                        //调转速
//                        // m.setAdjustLight(Integer.parseInt(c.getData(),16)+"");
//                    } else if (c.getFunction().equals("14")) {
//                        //调光照
//                        // m.setAdjustSpeed(Integer.parseInt(c.getData(),16)+"");
//                    }
//
//                }
            }
        } catch (StringIndexOutOfBoundsException s) {
            s.printStackTrace();
            //socketChannel.close();
           // demoService.saveService("StringIndexOutOfBoundsException:" + s.getMessage() + selectionKey.channel().toString());
        } catch (ClosedChannelException c) {

            c.printStackTrace();
           // demoService.saveService("ClosedChannelException:" + c.getMessage() + selectionKey.channel().toString());
            selectionKey.channel().close();

        } catch (BufferUnderflowException b) {
            b.printStackTrace();
           // demoService.saveService("BufferUnderflowException:" + b.getMessage() + selectionKey.channel().toString());
            selectionKey.channel().close();
        } catch (UnsupportedOperationException u) {
            u.printStackTrace();
          //  demoService.saveService("UnsupportedOperationException:" + u.getMessage() + selectionKey.channel().toString());
            selectionKey.channel().close();
        } catch (IOException io) {
            io.printStackTrace();
          //  demoService.saveService("IOException:" + io.getMessage() + selectionKey.channel().toString());
            selectionKey.channel().close();
        } catch (Exception e) {
           // demoService.saveService("Exception:" + e.getMessage() + selectionKey.channel().toString());
            e.printStackTrace();
            selectionKey.channel().close();
        }


    }

    private String str2HexStr(byte[] bss, int count) {
        char[] chars = "0123456789ABCDEF".toCharArray();
        StringBuilder sb = new StringBuilder("");
        int bit;
        byte[] bs = bss;
        for (int i = 0; i < count; i++) {
            bit = (bs[i] & 0x0f0) >> 4;
            sb.append(chars[bit]);
            bit = bs[i] & 0x0f;
            sb.append(chars[bit]);
        }
        return sb.toString();
    }

    private byte[] toBytes(String str) {
        if (str == null || str.trim().equals("")) {
            return new byte[0];
        }

        byte[] bytes = new byte[str.length() / 2];
        for (int i = 0; i < str.length() / 2; i++) {
            String subStr = str.substring(i * 2, i * 2 + 2);
            bytes[i] = (byte) Integer.parseInt(subStr, 16);
        }

        return bytes;
    }

    public void send(SelectionKey selectionKey, CommContent c) throws IOException {

        ServerSocketChannel serverSocketChannel = null;
        SocketChannel socketChannel = null;
        String requestMsg = "";
        int count = 0;
        if (selectionKey.isAcceptable()) {
            //每有客户端连接，即注册通信信道为可读
            serverSocketChannel = (ServerSocketChannel) selectionKey.channel();
            socketChannel = serverSocketChannel.accept();
            socketChannel.configureBlocking(false);
            socketChannel.register(selector, SelectionKey.OP_READ);
        } else if (selectionKey.isReadable()) {
            socketChannel = (SocketChannel) selectionKey.channel();
            rBuffer.clear();
            count = socketChannel.read(rBuffer);
            List chars = new ArrayList();
            String r = EEs.getStrByCommContent(c);

            //返回数据
            sBuffer = ByteBuffer.allocate(r.getBytes("GBK").length);
            sBuffer.put(toBytes(r));
            sBuffer.flip();
            socketChannel.write(sBuffer);

        }
    }


    private String setTemperature(String data) {

        if ("00".equals(data.substring(0, 2))) {
            int wd10 = Integer.parseInt(data, 16);
            double f = (double) wd10;
            Double b = f / 10;
            return "+" + b.toString();
        } else if ("01".equals(data.substring(0, 2))) {
            data = data.replace(data.substring(0, 2), "00");
            int wd10 = Integer.parseInt(data, 16);
            double f = (double) wd10;
            Double b = f / 10;
            return "-" + b.toString();
        } else {
            return "数据有误";
        }
    }
    private String setWindSpeed(String data) {
            int wd10 = Integer.parseInt(data, 16);
            double f = (double) wd10;
            Double b = f / 10;
            return  b.toString();
    }


    public void setMachine(CommContent c) {
        if (c.getFunction().equals("01")) {
            EEs.machine.setTemperature(setTemperature(c.getData()));
        } else if (c.getFunction().equals("02")) {
            //湿度
            EEs.machine.setHumidity(Integer.parseInt(c.getData(), 16) + "");
        } else if (c.getFunction().equals("03")) {
            //风向
            EEs.machine.setWindDirection(Integer.parseInt(c.getData(), 16) + "");
        } else if (c.getFunction().equals("04")) {
            //风速
            EEs.machine.setWindSpeed(setWindSpeed(c.getData()));
        } else if (c.getFunction().equals("05")) {
            EEs.machine.setBeiruqin(true);
//               //电子围栏    开关量
            String data = c.getData();
            String str = data.substring(data.length() - 1, data.length());
            if (str.equals("1")) {
                EEs.machine.setBeiruqin(true);
            } else {
                EEs.machine.setBeiruqin(false);
            }
        } else if (c.getFunction().equals("06")) {
            //红外感应    开关量
            String data = c.getData();
            String str = data.substring(data.length() - 1, data.length());
            if (str.equals("1")) {
                //检测到人体的存在
                EEs.machine.setInfraredInduction("有");
            } else {
                EEs.machine.setInfraredInduction("无");
            }
        } else if (c.getFunction().equals("07")) {
            //光照度传感器
            EEs.machine.setLightIntensity(Integer.parseInt(c.getData(), 16) + "");
        } else if (c.getFunction().equals("08")) {
            //烟雾传感器   开关量
           // m.setSmokeSensor((Integer.parseInt(c.getData(), 16)) + "");
        } else if (c.getFunction().equals("09")) {
            //触摸开关     开关量   前台显示即可
            //m.setTouchSwitch((Integer.parseInt(c.getData(),16))+"");
            if (c.getData().equals("000000000001")) {
                EEs.machine.setTouchSwitch("开");
            } else {
                EEs.machine.setTouchSwitch("关");
            }

        } else if (c.getFunction().equals("0b")) {
            // EEs.machine.setAlarmLamp(null);
            //光报警  0关  1开*****
            String data = c.getData();
            String str = data.substring(data.length() - 1, data.length());
            if (str.equals("1")) {
                //命令光报警打开
                EEs.machine.setAlarmLamp("01");
            } else {
                EEs.machine.setAlarmLamp("00");
            }
        }/*else if (c.getFunction().equals("0d")){
                //电机
            EEs.machine.setAdjustSpeed("open");
        }*/

    }


}


